package com.succez.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.succez.server.servlet.Consts;
import com.succez.server.servlet.ConnectionHandleTask;
import com.succez.server.servlet.config.ConfigReader;
import com.succez.server.servlet.config.XMLConfigReader;
import com.succez.server.servlet.http.WebApp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 服务器类
 */
public class Server {

    /**
     * 服务器端监听socket
     */
    private ServerSocket serverSocket;

    /*
     * 是否关闭服务器
     */
    private volatile boolean isShutdown = false;

    /**
     * slf4j+jdk-logging
     */
    private static Logger logger = LoggerFactory.getLogger(Server.class);

    /**
     * 配置读取器
     */
    private ConfigReader configReader;

    /**
     * 配置文件位置
     */
    private String configPath;

    /**
     * 是否需要配置文件
     */
    private boolean isConfigFile;

    /**
     * 线程池，固定为10个线程
     */
    private final static ExecutorService threadPool = Executors.newFixedThreadPool(10);

    /**
     * 默认解析XML配置文件，配置文件默认位于ConstVariable.CONFIG_PATH
     */
    public Server() {
        this(new XMLConfigReader(), "", true);
    }

    /**
     * 指定特定的配置读取器，如果指定需要配置文件，则会使用默认值
     * 
     * @param configReader 配置读取器
     * @param isConfigFile 是否使用配置文件
     */
    public Server(ConfigReader configReader, boolean isConfigFile) {
        this(configReader, "", isConfigFile);
    }

    /**
     * 指定特定的配置读取器，指定配置文件，指定是否使用配置文件，如果不使用，第二项则可以为""
     * 
     * @param configReader
     * @param configPath
     * @param isConfigFile
     */
    public Server(ConfigReader configReader, String configPath, boolean isConfigFile) {
        this.configReader = configReader;
        this.isConfigFile = isConfigFile;
        if (this.isConfigFile) {
            if (configPath == null || configPath.trim().equals("")) {
                this.configPath = Consts.CONFIG_PATH;
            } else {
                this.configPath = configPath;
            }
        } else {
            this.configPath = "";
        }
    }

    /**
     * 启动服务器，创建ServerSocket，读取配置并进行初始化配置
     * 
     * @throws Exception
     */
    public void start() throws Exception {
        this.start(Consts.PORT);
    }

    public void start(int port) throws Exception {
        // 进行配置解析
        parseConfig();
        // 进行ServerSocket创建
        serverSocket = new ServerSocket(port);
        String address = "localhost";
        address = serverSocket.getInetAddress().getLocalHost().getHostAddress();
        logger.info("服务启动成功,访问地址  " + "http://" + address + ":" + port);
        // 对外提供服务
        service();
    }

    /**
     * 解析配置
     * 
     * @return 如果解析失败则终止系统初始化
     */
    public void parseConfig() throws Exception {
        if (isConfigFile) {
            WebApp.servletContext = configReader.parse(configPath);
        } else {
            WebApp.servletContext = configReader.parse();
        }
        if (WebApp.servletContext == null) {
            throw new RuntimeException("未完成初始化设置");
        }
    }

    /**
     * 创建ConnectionHandleTask来处理连接
     */
    public void service() {
        Socket connection;
        ConnectionHandleTask task;
        while (!isShutdown) {
            try {
                connection = serverSocket.accept();
                task = new ConnectionHandleTask(connection);
                threadPool.execute(task);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 停止服务器并释放资源
     */
    public void stop() {
        isShutdown = true;
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}